#include "viewer.h"

#include <string>
#include <iostream>

#ifdef _MAC_OS_
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#endif

using namespace std;

Viewer::Viewer():
  _halfSize(0.5),
  _growing(true){
  }


Viewer::~Viewer(){

}


////////////////////////////////////////////////////////////////////////////////
// GL stuff

// initialize OpenGL context
void
Viewer::init(int w, int h){
  // background color
  glClearColor (0.0, 0.0, 0.0, 1.0);

  // viewport
  glViewport (0, 0, w, h);
    
  // square init
    _square.setDim(0.5, 0.5);
    _square.setPos(0, 0);
    _square.setColor(0, 1, 0);
}

void
Viewer::reshape(int w, int h){
  glViewport (0, 0, w, h);
}


/*!
   callback to draw graphic primitives
   you may edit it if you want to change de drawing procedure (add new objects
   for example).
 */
void
Viewer::display() const{
  // clear current buffer
  glClear (GL_COLOR_BUFFER_BIT);

  // define projetion matrix
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity (); 
  glOrtho (-1.1, 1.1, -1.1, 1.1, -10, 10);

  // define model view matrix
  glMatrixMode (GL_MODELVIEW);
  glLoadIdentity ();

  /////////////////////////////////////
  // Draw the primitives.
  //
  drawRedSquare();
  //
  // End of drawing
  /////////////////////////////////////

  glFlush();
}

/*!
   draw a simple red square. 
   This function illustrate how to render simple 2D geometry in OpenGL
*/
void
Viewer::drawRedSquare () const
{
  // Specify the color in RGB in [0;1] range.
  glColor3f(_square.getColor().getX(),
            _square.getColor().getY(),
            _square.getColor().getZ());

  // Begin OpenGL call : display two triangles to have a square
  // This square is positionned in [-0.5, -0.5] and have a width
  // and a height equals to 1.
    
  /*glBegin (GL_TRIANGLES);
  glVertex2f (-_halfSize, _halfSize);
  glVertex2f (-_halfSize, -_halfSize);
  glVertex2f (_halfSize, -_halfSize);

  glVertex2f (_halfSize, -_halfSize);
  glVertex2f (_halfSize, _halfSize);
  glVertex2f (-_halfSize, _halfSize);*/
    glBegin (GL_TRIANGLES);
    glVertex2f (_square.getPos().getX(), _square.getPos().getY());
    glVertex2f (_square.getPos().getX()+_square.getDim().getX(), _square.getPos().getY());
    glVertex2f (_square.getPos().getX(), _square.getPos().getY()+_square.getDim().getY());
    
    glVertex2f (_square.getPos().getX()+_square.getDim().getX(), _square.getPos().getY());
    glVertex2f (_square.getPos().getX(), _square.getPos().getY()+_square.getDim().getY());
    glVertex2f (_square.getPos().getX()+_square.getDim().getX(), _square.getPos().getY()+_square.getDim().getY());
  glEnd ();
}

void 
Viewer::updateScene () {
   if (_growing){ // grow square
        _halfSize += 0.0001;
       _square.setPos(_square.getPos().getX()+ 0.0001, _square.getPos().getY()+ 0.0001);
       _square.setPos(_square.getDim().getX()+ 0.0001, _square.getDim().getY()+ 0.0001);

        _growing = _halfSize < 0.7; // grow square until _halfSize >= 0.8
   } else {
        _halfSize -= 0.0001;
       _square.setPos(_square.getPos().getX()- 0.0001, _square.getPos().getY()- 0.0001);
              _square.setPos(_square.getDim().getX()- 0.0001, _square.getDim().getY()- 0.0001);
	_growing = _halfSize < 0.4;// grow square until _halfSize <= 0.3
   }

   display();
}


////////////////////////////////////////////////////////////////////////////////
// Events

/*!
   callback to manage mouse : called when user press or release mouse button
   You can change in this function the way the user 
   interact with the system.
 */
void  
Viewer::mousePressed(int button, int state, int x, int y){
   std::string buttonName;

   switch(button){
   case GLUT_LEFT_BUTTON:
      buttonName = string("left");
      break;
   case GLUT_MIDDLE_BUTTON:
      buttonName = string("middle");
      break;
   case GLUT_RIGHT_BUTTON:
      buttonName = string("right");
      break;
   default:
      buttonName = string("invalid");
   }

   cout << "User " 
        << (state == GLUT_DOWN ? "press " : "release ")
        << buttonName.c_str()
        << " button in "
        << x 
        << ", "
        << y
        << endl;

   // request display refresh
   glutPostRedisplay(); 
}


 
 
/*!
   callback to manage mouse : called when user move mouse with button pressed
   You can change in this function the way the user 
   interact with the system.
 */
void
Viewer::mouseMoved(int x, int y){
     cout << "Mouse moved in "
        << x 
        << ", "
        << y
        << endl;

   // request display refresh
   glutPostRedisplay(); 
}


/*!
   callback to manage keyboard interactions
   You can change in this function the way the user 
   interact with the system.
 */
void
Viewer::keyPressed(unsigned char key, int x, int y){

}
